#include <vtkForceDirectedLayoutStrategy.h>
#include <vtkGraphLayoutView.h>
#include <vtkMutableUndirectedGraph.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>

#include <vtkArcSource.h>
#include <vtkPolyDataMapper.h>
#include "vtkPolygon.h"
#include "vtkProperty.h"

#include "vtkLookupTable.h"
#include "vtkMinimalStandardRandomSequence.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"

#include "vtkGlyph3DMapper.h"
#include "vtkSphereSource.h"

#include "vtkInteractorStyleTrackballCamera.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkMapper2D.h"
#include "vtkActor2D.h"
#include "vtkCamera.h"
#include "vtkProperty2D.h"
#include "vtkProp3D.h"

int main(int, char*[]) {
    vtkNew<vtkRenderer> renderer;
    vtkNew<vtkRenderWindow> renderWindow;
    renderWindow->SetWindowName("RegularPolygonSource");
    renderWindow->AddRenderer(renderer);
    vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
//    renderWindowInteractor->SetInteractorStyle(vtkNew<vtkInteractorStyleTrackballCamera>)
    renderWindowInteractor->SetRenderWindow(renderWindow);


    vtkNew<vtkNamedColors> colors;


    const int RowCount = 36;
    const int ColCount = 40;
    const double RowDegree = vtkMath::Pi() * 2 / RowCount;
    const double Radius = 500;
    const int AreaAvgRadius = Radius / ColCount;
    const int ArcSegmentCount = 1;
    double ArcSegmentDegree = RowDegree / ArcSegmentCount;

    vtkNew<vtkCellArray> allPolygons;
    vtkNew<vtkPoints> allPoints;
    vtkNew<vtkPolyData> polygonPolyData;

    for (int i = 0; i < RowCount; ++i) {

        double degree = RowDegree * i;

        for (int j = 0; j < ColCount; ++j) {

            vtkNew<vtkPolygon> polygon;
            polygon->GetPointIds()->SetNumberOfIds((ArcSegmentCount + 1) * 2);
            vtkIdType numberOfPoints = allPoints->GetNumberOfPoints();

            double radius0 = j * AreaAvgRadius;
            double radius1 = (j + 1) * AreaAvgRadius;

            for (int k = 0; k < ArcSegmentCount + 1; ++k) {
                double d0 = degree + (ArcSegmentDegree) * k;
                double x0 = cos(d0) * radius0;
                double y0 = sin(d0) * radius0;
                allPoints->InsertNextPoint(x0, y0, 0.0);

                double d1 = degree + (ArcSegmentDegree) * k;
                double x1 = cos(d1) * radius1;
                double y1 = sin(d1) * radius1;
                allPoints->InsertNextPoint(x1, y1, 0.0);

                polygon->GetPointIds()->SetId(k, numberOfPoints + (ArcSegmentCount - k));
                polygon->GetPointIds()->SetId(k + ArcSegmentCount + 1, numberOfPoints + ArcSegmentCount + 1 + k);
            }

            allPolygons->InsertNextCell(polygon);
        }
    }

    polygonPolyData->SetPoints(allPoints);
    polygonPolyData->SetPolys(allPolygons);


//    vtkNew<vtkPolyDataMapper2D> mapper;
//    mapper->SetInputData(polygonPolyData);
//    vtkSmartPointer<vtkCoordinate> normCoords = vtkSmartPointer<vtkCoordinate>::New();
//    normCoords->SetCoordinateSystemToView();
//    mapper->SetTransformCoordinate( normCoords );

//    vtkNew<vtkActor2D> actor;
//    actor->SetMapper(mapper);
////    actor->GetProperty()->EdgeVisibilityOn();
//    actor->GetProperty();
//    renderer->AddActor2D(actor);

    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetInputData(polygonPolyData);

    vtkNew<vtkActor> actor;
    actor->SetMapper(mapper);
    actor->GetProperty()->EdgeVisibilityOn();
    actor->GetProperty();
    renderer->AddActor(actor);

    actor->RotateX(30);
    actor->RotateY(50);

//    vtkSmartPointer<vtkProp3D> ssss = actor->RotateX(-30);
    double *ssss = actor->GetOrientation();
//    ssss->Get

    actor->RotateX(-30);
    actor->RotateY(-50);

    std::cout << ssss[0] << ":::" << ssss[1] << ":::";

//    vtkNew<vtkCamera> camera2;
//    camera2->SetPosition(0, 0, 1);
//    camera2->SetFocalPoint(0, 0, 0);
//    camera2->SetViewUp(0, 1, 0);
//    camera2->SetParallelScale(500);
//    camera2->ParallelProjectionOn();
//    renderer->SetActiveCamera(camera2);
//    renderer->ResetCameraClippingRange();

    vtkNew<vtkCamera> camera;
    camera->SetPosition(0, 0, 1400);
    camera->SetFocalPoint(0, 0, 0);
    camera->SetViewUp(0, 1, 0);
    renderer->SetActiveCamera(camera);
//    camera->SetClippingRange(0, 2000);
    renderer->ResetCameraClippingRange();
    renderWindow->Render();



    // 测试变化裁剪范围
    {
        double allBounds[6];
        renderer->ComputeVisiblePropBounds(allBounds);

        for (int i = 0; i < 6; ++i) {
            std::cout << i << "---:  " << allBounds[i] << std::endl;
        }
        std::cout << camera->GetClippingRange()[0] << "-" << camera->GetClippingRange()[1];

        allBounds[4] = 100;
        renderer->ResetCameraClippingRange(allBounds);
    }



    renderWindow->Render();
//    renderWindowInteractor->Disable();
    renderWindowInteractor->Initialize();
    renderWindowInteractor->Start();







    //    renderWindow->GetRenderers()[0]
//    vtkActorCollection* actors = renderer->GetActors();
//    vtkSmartPointer<vtkPolyData> ringActorData;
//
//    if (renderer->GetActors()->GetNumberOfItems() > 0) {
//        auto aaa = renderer->GetActors()->GetItemAsObject(0);
//
//        vtkSmartPointer<vtkActor> actt = static_cast<vtkActor*>(aaa);
//        vtkSmartPointer<vtkActor> actt2 = static_cast<vtkActor*>(aaa);
//        vtkSmartPointer<vtkActor> actt3 = static_cast<vtkActor*>(aaa);
//
//        ringActorData = static_cast<vtkPolyData*>(actt->GetMapper()->GetInput());
//        vtkSmartPointer<vtkPolyData> ringActorData2 = static_cast<vtkPolyData*>(actt->GetMapper()->GetInput());
//        vtkSmartPointer<vtkPolyData> ringActorData3 = static_cast<vtkPolyData*>(actt->GetMapper()->GetInput());
//    }


//    vtkNew<vtkUnsignedCharArray> cellData;
//    cellData->SetNumberOfComponents(3);
//    cellData->SetNumberOfTuples(polygonPolyData->GetNumberOfCells());
//
//    vtkNew<vtkMinimalStandardRandomSequence> randomSequence;
//    randomSequence->SetSeed(8775070);
//    auto min_r = 64.0;
//    auto max_r = 255.0;
//    for (int i = 0; i < polygonPolyData->GetNumberOfCells(); i++)
//    {
//        double rgb[3];
//        for (auto j = 0; j < 3; ++j)
//        {
//            rgb[j] = randomSequence->GetRangeValue(min_r, max_r);
//            randomSequence->Next();
//        }
//        cellData->InsertTuple(i, rgb);
//    }


//    polygonPolyData->GetCellData()->SetScalars(cellData);
//    actor->Modified();
//    renderWindow->Render();
//    renderWindowInteractor->Render();



    return EXIT_SUCCESS;
}